package br.com.unifebe.tcc.DAO;

import java.util.Collection;

import org.hibernate.Criteria;
import org.hibernate.Hibernate;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;

import br.com.unifebe.tcc.UTILS.HibernateUtils;
import br.com.unifebe.tcc.model.Usuario;
@SuppressWarnings({"rawtypes","unchecked"})
public class DAOimpl<E extends Object> implements DAO<E>{

	private static DAOimpl instance;

	public static DAOimpl getInstance(){
		if(instance == null){
			instance = new DAOimpl();
		}
		return instance;
	}
	
	@Override
	public void save(E object) {
		Session session = HibernateUtils.getSessionFactory().openSession();
		Transaction t = session.beginTransaction();
		session.saveOrUpdate(object);
		t.commit();
		session.close();
	}
	
	public E getPorId(Long id) {
		Session session = HibernateUtils.getSessionFactory().openSession();
		return  (E) session.load(Object.class, id);
	}

	@Override
	public Collection<E> getListaTodos(){
		Session session = HibernateUtils.getSessionFactory().openSession();
		Transaction t = session.beginTransaction();
		Collection<E> lista = session.createCriteria(Object.class).list();
		t.commit();
		session.close();
		return lista;
	}

	@Override
	public void remove(E objeto) {
		Session session = HibernateUtils.getSessionFactory().openSession();
		Transaction t = session.beginTransaction();
		session.delete(objeto);
		t.commit();
		session.close();
	}

	@Override
	public void update(E objeto) {
		Session session = HibernateUtils.getSessionFactory().openSession();
		Transaction t = session.beginTransaction();
		session.update(objeto);
		t.commit();
		session.close();
	}
	
	@SuppressWarnings("unchecked")
	@Override
	public E buscarUltimo() {
		Session session = HibernateUtils.getSessionFactory().openSession();
		Transaction t = session.beginTransaction();
		Criteria crit = session.createCriteria(Object.class);
		crit.addOrder( Order.desc("id") )
		.setMaxResults(1);
		E e = null;
		Collection<E> lista = crit.list();
		t.commit();
		for (E e2 : lista) {
			e = e2;
		}
		session.close();
		return e;
	}
	
	
	@SuppressWarnings("unchecked")
	@Override
	public E buscarPrimeiro() {
		Session session = HibernateUtils.getSessionFactory().openSession();
		Transaction t = session.beginTransaction();
		Criteria crit = session.createCriteria(Object.class);
		crit.addOrder( Order.asc("id") )
		.setMaxResults(1);
		E e = null;
		Collection<E> lista = crit.list();
		t.commit();
		for (E e2 : lista) {
			e = e2;
		}
		return e;
	}
	
	public E buscarAnterior(Long o ) {
		Session session = HibernateUtils.getSessionFactory().openSession();
		Transaction t = session.beginTransaction();
		Criteria crit = session.createCriteria(Object.class);
		crit.add( Restrictions.sqlRestriction("{alias}.id < (?)", o, Hibernate.LONG));
		crit.addOrder( Order.desc("id") )
		.setMaxResults(1);
		E e = null;
		Collection<E> lista = crit.list();
		t.commit();
		for (E e2 : lista) {
			e = e2;
		}
		return e;
	}

	public E buscarProximo(Long o) {
		Session session = HibernateUtils.getSessionFactory().openSession();
		Transaction t = session.beginTransaction();
		Criteria crit = session.createCriteria(Object.class);
		crit.add( Restrictions.sqlRestriction("{alias}.id > (?)", o, Hibernate.LONG));
		crit.addOrder( Order.asc("id") )
		.setMaxResults(1);
		E e = null;
		Collection<E> lista = crit.list();
		t.commit();
		for (E e2 : lista) {
			e = e2;
		}
		return e;
	}

	public Boolean login( String login, String senha ) {
		Session session = HibernateUtils.getSessionFactory().openSession();
		Transaction t = session.beginTransaction();
		Criteria crit = session.createCriteria(Usuario.class);
		
		crit.add( Restrictions.eq( "login", login ) );
		crit.add( Restrictions.eq( "senha", senha ) );

		crit.addOrder( Order.asc("id") )
		.setMaxResults(1);
		
		E e = null;
		Collection<E> lista = crit.list();
		t.commit();
		for (E e2 : lista) {
			e = e2;
		}
		
		return ( e != null );
	}
}
